//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Diagnostics.Contracts;
using OpenLS.Spreadsheet.Expressions;

namespace OpenLS.Spreadsheet.Formats.Biff.Tokens
{
    internal sealed class RefToken : FormulaToken
    {
        private readonly AccessorType _type;

        public RefToken(AccessorType type)
        {
            _type = type;
        }

        public RefToken(ushort rowIndex, short columnIndex, bool isRelativeRow, bool isRelativeColumn, AccessorType type):
            this(type)
        {
            this.RgceLocRel = new RgceLocRel(rowIndex, columnIndex, isRelativeRow, isRelativeColumn);
        }

        private RgceLocRel RgceLocRel;

        public override ushort GetLength(FormulaReadContextType formulaReadContextType)
        {
            switch (formulaReadContextType)
            {
                case FormulaReadContextType.Default:
                    return 4;
                    case FormulaReadContextType.ExternName:
                    return 6;
                    default:
                    // Contract.Assert(false);
                    throw new NotSupportedException();

            }
            return 4;
        }

        internal override void ReadContent(FormulaReadContext context)
        {
            this.RgceLocRel.Read(context.Reader);
/*            _rowIndex = context.ReadUInt16();
            ushort i2 = context.ReadUInt16();
            switch (context.Type)
            {

                case FormulaReadContextType.Default:
                    _columnIndex = (ushort) (i2 & 0x00FF);
                    _isRelativeColumn = (i2 & relativeColumnMask) != 0;
                    _isRelativeRow = (i2 & relativeRowMask) != 0;
                    break;
                case FormulaReadContextType.ExternName:
                    _columnIndex = (ushort)(i2 & 0x00FF);
                    _isRelativeColumn = context.ReadByte() != 0;
                    _isRelativeRow = context.ReadByte() != 0; //\\ order?
                    break;
                default:
                    Contract.Assert(false);
                    break;
            }
  */      }

        public override void WriteContent(FormulaWriteContext context)
        {
            this.RgceLocRel.Write(context.Writer);
            /*
            context.WriteUInt16(_rowIndex);
            ushort i2 = _columnIndex;
            switch (context.Type)
            {

                case FormulaReadContextType.Default:
                    {
                        if (_isRelativeRow)
                            i2 |= relativeRowMask;
                        if (_isRelativeColumn)
                            i2 |= relativeColumnMask;
                        context.WriteUInt16(i2);
                    }
                    break;
                case FormulaReadContextType.ExternName:
                    {
                        context.WriteUInt16(i2);
                        byte b;
                        b = (byte)(_isRelativeColumn ? 1 : 0);
                        context.WriteByte(b);
                        b = (byte)(_isRelativeRow ? 1 : 0);
                        context.WriteByte(b);
                    }
                    break;
                default:
                    Contract.Assert(false);
                    throw new NotSupportedException();
                    break;
            }*/
        }

        public override FormulaTokenId TokenId
        {
            get {
                switch (_type)
                {
                        case AccessorType.Array:
                        return FormulaTokenId.RefA;
                        case AccessorType.Reference:
                        return FormulaTokenId.Ref;
                        case AccessorType.Value:
                        return FormulaTokenId.RefV;
                    default:
                        throw new NotSupportedException();
                }
            }
        }

        public AccessorType Type
        {
            get {
                return _type;
            }
        }

        internal override Expression GetExpression(FormulaEvaluationContext context)
        {
            Worksheet caller = null;
            if (context.WorksheetContext != null)
                caller = context.WorksheetContext.Worksheet;
            return new CellReferenceExpression(new StaticCellReference(
                                                   new AnchoredRowReference(context.Worksheet.Rows[this.RgceLocRel.RowIndex],
                                                                            !this.RgceLocRel.IsRelativeRow),
                                                   new AnchoredColumnReference(context.Worksheet.Columns[this.RgceLocRel.ColumnIndex],
                                                                               !this.RgceLocRel.IsRelativeColumn)), caller);
        }
    }
}